package com.lonely.web.controller.websocket;

import cn.dev33.satoken.annotation.SaCheckPermission;
import com.lonely.common.core.redis.RedisCache;
import com.lonely.common.exception.BusinessException;
import com.lonely.common.exception.RedisLockException;
import com.lonely.common.threadlocals.LoginUserThreadLocal;
import com.lonely.common.utils.SecurityUtils;
import com.lonely.deliver.domain.dto.SyncProgressDTO;
import com.lonely.framework.websocket.CustomWebSocketPrincipal;
import com.lonely.framework.websocket.WebSocketRequest;
import com.lonely.framework.websocket.WebSocketUtil;
import com.lonely.order.service.IOrderService;
import com.lonely.order.support.synchronizer.SynchronizedOrderDeliverThreadLocal;
import com.lonely.order.support.synchronizer.service.SynchronizerOrderDeliverService;
import com.lonely.order.threadlocals.OrderSynchronizedThreadLocal;
import lombok.RequiredArgsConstructor;
import lombok.SneakyThrows;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.exception.ExceptionUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.messaging.handler.annotation.MessageMapping;
import org.springframework.messaging.handler.annotation.Payload;
import org.springframework.messaging.simp.stomp.StompHeaderAccessor;
import org.springframework.web.bind.annotation.RestController;

import java.util.concurrent.TimeUnit;

/**
 * WebSocket 测试控制器
 *
 * @author fzzf
 */
@RestController
//@RequestMapping("/websocket")
@RequiredArgsConstructor
@Slf4j
public class WebsocketController {

    @Autowired
    private SynchronizerOrderDeliverService synchronizerOrderDeliverService;

    @Autowired
    private IOrderService orderService;

    @Autowired
    private RedisCache redisCache;

    /**
     * 同步订单发货单
     */
    @SneakyThrows
    @MessageMapping("/synchronizeDeliver")
    @SaCheckPermission("orderDeliver:deliver:synchronizeDeliver")
    public void synchronizeDeliver(@Payload WebSocketRequest request, StompHeaderAccessor headerAccessor) {
        CustomWebSocketPrincipal webSocketPrincipal = (CustomWebSocketPrincipal) headerAccessor.getUser();
        if (webSocketPrincipal == null) {
            throw new BusinessException("用户未登录");
        }

        String username = webSocketPrincipal.getName();
        String destination = String.format("/queue/deliverSyncProgress/%s", request.getRequestId());
        new Thread(() -> {
            LoginUserThreadLocal.setLoginUser(webSocketPrincipal.getLoginUser());
            SynchronizedOrderDeliverThreadLocal.setIsWebsocket(true);
            SynchronizedOrderDeliverThreadLocal.setDestination(destination);
            SynchronizedOrderDeliverThreadLocal.setCreateBy(SecurityUtils.getUserId());
            try {
                this.synchronizerOrderDeliverService.synchronizerOrderDeliver();
            } catch (RedisLockException e) {
                log.error("有其他进程在同步发货单数据,请稍后再试");
                WebSocketUtil.sendToUser(username, destination, SyncProgressDTO.buildErrorResult("有其他进程在同步发货单数据,请稍后再试"));
            } catch (Exception e) {
                log.error("同步异常,异常原因：{}", ExceptionUtils.getStackTrace(e));
                WebSocketUtil.sendToUser(username, destination, SyncProgressDTO.buildErrorResult(String.format("同步异常,异常原因：%s", e.getMessage())));
            } finally {
                SynchronizedOrderDeliverThreadLocal.remove();
                LoginUserThreadLocal.remove();
            }
        }).start();

    }


    /**
     * 同步订单
     */
    @SneakyThrows
    @MessageMapping("/synchronizeOrder")
    public void synchronizeOrder(@Payload WebSocketRequest request, StompHeaderAccessor headerAccessor) {
        CustomWebSocketPrincipal webSocketPrincipal = (CustomWebSocketPrincipal) headerAccessor.getUser();
        if (webSocketPrincipal == null) {
            throw new BusinessException("用户未登录");
        }

        String username = webSocketPrincipal.getName();
        String destination = String.format("/queue/orderSyncProgress/%s", request.getRequestId());

        // 判断是否调用频率太快，要求同一个用户调用频率最少间隔10分钟
        boolean acquired = this.redisCache.tryLock("order:synchronize:lock:", username, username, 10, TimeUnit.MINUTES);
        if (!acquired) {
            // 已存在锁，说明 10 分钟内调用过
            WebSocketUtil.sendToUser(username, destination, SyncProgressDTO.buildErrorResult("操作过于频繁，请10分钟后再试"));
            return;
        }

//        for (int i = 0; i < 100; i++) {
//            WebSocketUtil.sendToUser(username, destination, SyncProgressDTO.buildProgressResult(i,""));
//            ThreadUtil.sleep(50);
//        }
//        WebSocketUtil.sendToUser(username, destination, SyncProgressDTO.buildCompletedResult("成功..."));

        // 执行同步逻辑
        LoginUserThreadLocal.setLoginUser(webSocketPrincipal.getLoginUser());
        OrderSynchronizedThreadLocal.setIsWebsocket(true);
        OrderSynchronizedThreadLocal.setDestination(destination);
        OrderSynchronizedThreadLocal.setCreateBy(SecurityUtils.getUserId());
        try {
            this.orderService.synchronizerLastMonthOrder();
        } catch (Exception e) {
            log.error("同步异常,异常原因：{}", ExceptionUtils.getStackTrace(e));
            WebSocketUtil.sendToUser(username, destination, SyncProgressDTO.buildErrorResult(String.format("同步异常,异常原因：%s", e.getMessage())));
        } finally {
            OrderSynchronizedThreadLocal.clear();
            LoginUserThreadLocal.remove();
        }
    }
}

